﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpCommandBase.h"

#include "ILine2d.h"
#include "Vector2dUtils.h"
#include "Vector3dUtils.h"
#include "ICurve3d.h"
#include "IPlane.h"
#include "AlgorithmProject.h"
#include "IArc3d.h"
#include "IGraphicsNodeGroup.h"
#include "IGridNew.h"
#include "StructureCmdIds.h"
#include "GmUiStructureCommandRegister.h"
#include "ActionBase.h"
#include "ActionDrawStraightElementInput.h"
#include "ActionDrawStraightElementCreator.h"
#include "ActionDrawArcBy3PtsElementInput.h"
#include "ActionDrawArcBy3PtsElementCreator.h"
#include "GbmpControlIds.h"
#include "AddStructureDynamicPannelUtil.h"
#include "GbmpPresetParameterUIUtils.h"
#include "GbmpGraphicsNodeUtils.h"

#include "IDocument.h"
#include "IElementBasicInformation.h"
#include "IUiView.h"
#include "IModelView.h"
#include "GridNewInput.h"
#include "GridNameManager.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IUserTransaction.h"
#include "UserTransactionGroupUtils.h"
#include "IGenericElement.h"


#include "IUiDocumentViewManager.h"
#include "GbmpModelViewTypes.h"
#include "GbmpSnapEndPointPriorityTypesPreprocessor.h"
#include "StructureInstancePresetParameterUtils.h"
#include "GridNewUtils.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

//////////////////////////////////////////////////////////////////////////
class CmdDrawGridNewBase : public GbmpCommandBase
{
public:
    explicit CmdDrawGridNewBase(const std::wstring& cmdId) 
        : GbmpCommandBase(cmdId),
        m_persetGridId(ElementId::InvalidID)
    {}

    virtual ~CmdDrawGridNewBase() {}

public:
    virtual bool IsVisible() const override { return true; }
    virtual bool IsEnabled() const override;

public:
    void OnActionInit(IUiView* pCurrentView);
    void OnActionDestroy();

protected:
    OwnerPtr<IGraphicsNodeGroup> CreatePreviewGraphics(IUiView* pCurrentView, const ICurve3d* pCurve);
    IGridNew* CreateGridElement(IUiView* pCurrentView, const ICurve3d* pCurve);

protected:
    ElementId m_persetGridId;
    int m_utxGroupIdx;
};

bool CmdDrawGridNewBase::IsEnabled() const
{
    if (!CommandBase::IsEnabled())
        return false;

    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pUiDocViewMgr, L"pUiDocViewMgr为空",L"GDMPLab",L"2024-03-30");

    IUiView* pUIView = pUiDocViewMgr->GetCurrentUiView();
    if (pUIView != nullptr)
    {
        IModelView* pModelView = pUIView->GetModelView();
        if (pModelView != nullptr)
        {
            if (PlanViewType == pModelView->GetUserDataId())

            {
                return true;
            }
        }
    }

    return false;
}

void CmdDrawGridNewBase::OnActionInit(IUiView* pCurrentView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    GridNewInput gridNewInput;
    gridNewInput.Document = pDoc;
    OwnerPtr<IPlane> opIPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_VOID_UNLESS(opIPlane, L"opIPlane为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.verticalExtents = GridNewUtils::GetGridDefaultVerticalExtents(pDoc, opIPlane.get(), ElementCreationOptions::Transient);
    GridNewUtils::setGridNewPresetParameter(pDoc,gridNewInput.StartTagVisble, gridNewInput.EndTagVisble);
    OwnerPtr<ILine2d> opLine = ILine2d::Create(Vector2d(0.0, 0.0), Vector2d(1.0, 0.0));
    DBG_WARN_AND_RETURN_VOID_UNLESS(opLine, L"opIPlane为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.VecOpCurve.push_back(TransferOwnership(opLine));
    gridNewInput.CreationOption = ElementCreationOptions::Transient;

    // 启动轴网事务组
    UserTransactionGroupUtils::Start(pDoc, GBMP_TR(L"轴网事务组"), m_utxGroupIdx);

    // 初始化预设参数
    OwnerPtr<IUserTransaction> opUtx = IUserTransaction::Create(pDoc, GBMP_TR(L"设置轴网预设参数"));
    StructureInstancePresetParameterUtils::SetPresetInstanceType(pDoc, BuiltInCategoryUniIdentities::BICU_NEW_GRID, 0, ElementId::InvalidID);
    opUtx->Commit();

    // 预设轴网设置隐藏
    gridNewInput.Visible = false;

    // 创建轴网
    IGridNew *pPresetGrid = IGridNew::Create(gridNewInput);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPresetGrid, L"pPresetGrid为空",L"GDMPLab",L"2024-03-30");

    // 为预设轴网申请下一个编号
    pPresetGrid->AutoName();

    // debug
    std::wstring lastActiveName = GridNameManager::GetLastActiveName(pDoc);
    OutputDebugString((lastActiveName + L"\n").c_str());
    std::wstring presetGridName = pPresetGrid->GetName();
    OutputDebugString((presetGridName + L"\n").c_str());

    ElementId presetGridId = pPresetGrid->GetOwnerElement()->GetElementId();
    auto element = pPresetGrid->GetOwnerElement();
    //保存预设轴网id
    m_persetGridId = presetGridId;
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(presetGridId);
}


void CmdDrawGridNewBase::OnActionDestroy()
{
    // 删除预设轴网
    if (m_persetGridId != ElementId::InvalidID)
    {
        UiDocumentViewUtils::GetCurrentDocument()->DeleteElement(m_persetGridId);
    }
    // 删除预设参数
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(ElementId::InvalidID);
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);

    // 回滚轴网事务组
    UserTransactionGroupUtils::Abort(UiDocumentViewUtils::GetCurrentDocument(), m_utxGroupIdx);
}

OwnerPtr<IGraphicsNodeGroup> CmdDrawGridNewBase::CreatePreviewGraphics(IUiView* pCurrentView, const ICurve3d* pCurve)
{
    OwnerPtr<IGraphicsNodeGroup> opRet = IGraphicsNodeGroup::Create();
    DBG_WARN_AND_RETURN_UNLESS(opRet, opRet, L"opRet为空",L"GDMPLab",L"2024-03-30");
    opRet->SetIsSnappable(false);

    DBG_WARN_AND_RETURN_UNLESS(pCurrentView, opRet, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pCurve, opRet, L"pCurve为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, opRet, L"无效的文档",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_UNLESS(pModelView, opRet, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_UNLESS(opWorkPlane, opRet, L"opWorkPlane为空",L"GDMPLab",L"2024-03-30");
    GridNewInput gridNewInput;
    gridNewInput.Document = pDoc;
    gridNewInput.verticalExtents = GridNewUtils::GetGridDefaultVerticalExtents(pDoc, opWorkPlane.get(), ElementCreationOptions::Transient);
    GridNewUtils::setGridNewPresetParameter(pDoc,gridNewInput.StartTagVisble, gridNewInput.EndTagVisble);
    OwnerPtr<ICurve2d> opCurve = AlgorithmProject::Project(pCurve, opWorkPlane.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opCurve, L"opCurve为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.VecOpCurve.push_back(TransferOwnership(opCurve));
    gridNewInput.CreationOption = ElementCreationOptions::Transient;

    // 创建临时预览轴网（临时对象，无需启动事务）
    IGenericElement* pPresetGenericElement = quick_cast<IGenericElement>(pDoc->GetElement(m_persetGridId));
    DBG_WARN_AND_RETURN_UNLESS(pPresetGenericElement, opRet, L"pPresetGenericElement为空",L"GDMPLab",L"2024-03-30");
    IGridNew* pPresetGrid = quick_cast<IGridNew>(pPresetGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_UNLESS(pPresetGrid, opRet, L"pPresetGenericElement为空",L"GDMPLab",L"2024-03-30");


    // debug
    std::wstring presetGridName = pPresetGrid->GetName();
    OutputDebugString((pPresetGrid->GetName() + L"\n").c_str());

    // 创建预览轴网
    IGridNew* pPreviewGrid = IGridNew::Create(gridNewInput);
    DBG_WARN_AND_RETURN_UNLESS(pPreviewGrid, opRet, L"pPreviewGrid为空",L"GDMPLab",L"2024-03-30");

    pPreviewGrid->GetOwnerElement()->GetBasicInformation()->SetName(pPresetGrid->GetName());

    // 刷新属性面板
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(m_persetGridId);

    // 生成临时预览轴网的ElementShape
    opRet = GbmpGraphicsNodeUtils::TransferGRepToGGroup(pPreviewGrid->CreateElementShapeBasedOnPlane(opWorkPlane.get(), pModelView->GetViewScale(),pModelView));

    // 删除临时预览轴网
    pDoc->DeleteElement(pPreviewGrid->GetOwnerElement()->GetElementId());

    return opRet;
}

IGridNew* CmdDrawGridNewBase::CreateGridElement(IUiView* pCurrentView, const ICurve3d* pCurve)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCurrentView != nullptr, L"当前视图为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCurve != nullptr, L"pCurve为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc != nullptr, L"无效的文档",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"view为空",L"GDMPLab",L"2024-03-30");

    IGenericElement* pPresetGenericElement = quick_cast<IGenericElement>(pDoc->GetElement(m_persetGridId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPresetGenericElement, L"pPresetGenericElement为空",L"GDMPLab",L"2024-03-30");
    IGridNew* pPresetGrid = quick_cast<IGridNew>(pPresetGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPresetGrid, L"pPresetGenericElement为空",L"GDMPLab",L"2024-03-30");
    GridNewInput gridNewInput;
    gridNewInput.Document = pDoc;
    OwnerPtr<IPlane> opIPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opIPlane, L"opIPlane为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.verticalExtents = GridNewUtils::GetGridDefaultVerticalExtents(pDoc, opIPlane.get(), ElementCreationOptions::Normal);
    GridNewUtils::setGridNewPresetParameter(pDoc,gridNewInput.StartTagVisble, gridNewInput.EndTagVisble);
    OwnerPtr<ICurve2d> opCurve = AlgorithmProject::Project(pCurve, opIPlane.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opCurve, L"opCurve为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.VecOpCurve.push_back(TransferOwnership(opCurve));
    // debug
    std::wstring presetGridName = pPresetGrid->GetName();
    OutputDebugString((presetGridName + L"\n").c_str());

    // 创建轴网
    OwnerPtr<IUserTransaction> opUtx = IUserTransaction::Create(pDoc, GBMP_TR(L"创建轴网"));
    IGridNew* pGrid = IGridNew::Create(gridNewInput);
    pGrid->SetName(pPresetGrid->GetName());
    opUtx->Commit();

    // 预设轴网申请下一个编号
    pPresetGrid->AutoName();

    // 更新预设参数的属性面板
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(m_persetGridId);

    return pGrid;
}

//////////////////////////////////////////////////////////////////////////
class CmdDrawLineGridNew : public CmdDrawGridNewBase
{
public:
    CmdDrawLineGridNew() : CmdDrawGridNewBase(ID_CMD_DRAWING_LINE_GRIDNEW) {}
    ~CmdDrawLineGridNew() {}

public:
    virtual OwnerPtr<IAction> ExecuteCommand(const CommandParameters& cmdParams) override;

public:
    ElementId OnLineFinished(
        IUiView* pCurrentView,
        const Vector3d& startPt,
        const Vector3d& endPt,
        const ISnap* pStartSnap,
        const ISnap* pEndSnap);

    OwnerPtr<IGraphicsNodeGroup> OnLineUpdate(
        IUiView* pCurrentView,
        const Vector3d& startPt,
        const Vector3d& endPt);

    const std::wstring DefinePromptMessage(DrawLineStatus drawLineStatus);

    void OnEnterGettingStartPointState(IUiView* pCurrentView);

    void OnEnterGettingEndPointState(IUiView* pCurrentView);
};

ElementId CmdDrawLineGridNew::OnLineFinished(
    IUiView* pCurrentView, 
    const Vector3d& startPt, 
    const Vector3d& endPt,
    const ISnap* pStartSnap, 
    const ISnap* pEndSnap)
{
    OwnerPtr<ILine3d> opLine = ILine3d::Create(startPt, endPt);
    IGridNew* pGrid = this->CreateGridElement(pCurrentView, opLine.get());
    DBG_WARN_AND_RETURN_UNLESS(pGrid, ElementId::InvalidID, L"pGrid为空，轴网创建失败。",L"GDMPLab",L"2024-03-30");

    // 提交事务组并合并为一个事务
    UserTransactionGroupUtils::CommitLatestActiveWithTransactionsMergedIntoOne(UiDocumentViewUtils::GetCurrentDocument());
    // 启动新的事务组
    UserTransactionGroupUtils::Start(UiDocumentViewUtils::GetCurrentDocument(), GBMP_TR(L"创建单条轴网事务组"), m_utxGroupIdx);

    return pGrid->GetOwnerElement()->GetElementId();
}

OwnerPtr<IGraphicsNodeGroup> CmdDrawLineGridNew::OnLineUpdate(
    IUiView* pCurrentView, 
    const Vector3d& startPt,
    const Vector3d& endPt)
{
    if (Vector2dUtils::IsEqual(startPt.Vec2d(), endPt.Vec2d()))
    {
        return nullptr;
    }

    OwnerPtr<ILine3d> opLine = ILine3d::Create(startPt, endPt);
    return CreatePreviewGraphics(pCurrentView, opLine.get());
}

const std::wstring CmdDrawLineGridNew::DefinePromptMessage(DrawLineStatus drawLineStatus)
{
    switch (drawLineStatus)
    {
    case DrawLineStatus::Getting_StartPoint:
        return GBMP_TR(L"绘制轴网 - 请输入轴网起始点");
    case DrawLineStatus::Getting_EndPoint:
        return GBMP_TR(L"绘制轴网 - 请输入轴网终止点");
    default:
        return L"";
    }
}

void CmdDrawLineGridNew::OnEnterGettingStartPointState(IUiView* pCurrentView)
{
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);
}

void CmdDrawLineGridNew::OnEnterGettingEndPointState(IUiView* pCurrentView)
{
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);
}

OwnerPtr<IAction> CmdDrawLineGridNew::ExecuteCommand(const CommandParameters& cmdParams)
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"文档为空",L"GDMPLab",L"2024-03-30");

    CmdDrawGridNewBase* pCmdBase = static_cast<CmdDrawGridNewBase*>(this);

    // 定制Action
    ActionDrawStraightElementInput actionInput;
    actionInput.CommandId = GetCommandId();
    actionInput.DrawLineMode = DrawLineMode::Separated;
    actionInput.PreviewLineEnabled = false;

    actionInput.ActionInitCallback = ActionDrawStraightElementInput::CreateOnActionInitCallback(&CmdDrawGridNewBase::OnActionInit, pCmdBase);
    actionInput.LineFinishedCallback = ActionDrawStraightElementInput::CreateOnLineFinishedCallback(&CmdDrawLineGridNew::OnLineFinished, this);
    actionInput.LineUpdateCallback = ActionDrawStraightElementInput::CreateOnLineUpdateCallback(&CmdDrawLineGridNew::OnLineUpdate, this);
    actionInput.PromptMessageCallback = ActionDrawStraightElementInput::CreateDefinePomptMessageCallback(&CmdDrawLineGridNew::DefinePromptMessage, this);
    actionInput.EnterGettingStartPointStateCallback = ActionDrawStraightElementInput::CreateOnEnterGettingStartPointStateCallback(
        &CmdDrawLineGridNew::OnEnterGettingStartPointState, this);
    actionInput.EnterGettingEndPointStateCallback = ActionDrawStraightElementInput::CreateOnEnterGettingEndPointStateCallback(
        &CmdDrawLineGridNew::OnEnterGettingEndPointState, this);
    actionInput.ActionDestroyCallback = ActionDrawStraightElementInput::CreateOnActionDestroyCallback(&CmdDrawGridNewBase::OnActionDestroy, pCmdBase);

    std::vector<Int64> priorityTypes;
    priorityTypes.emplace_back(typeid(IGridNew).hash_code());
    actionInput.SnapCandidatesPreprocessor = NEW_AS_OWNER_PTR(GbmpSnapEndPointPriorityTypesPreprocessor, priorityTypes);

    OwnerPtr<IAction> opAction = ActionDrawStraightElementCreator::Create(actionInput);

    // 开启动态面板
    AddStructureDynamicPannelUtil::SetupGridNewCreationContext(opAction.get(), ID_PAGE_GBMP_MODIFY);

    return TransferOwnership(opAction);
}

//////////////////////////////////////////////////////////////////////////
class CmdDrawArcBy3PtsGridNew : public CmdDrawGridNewBase
{
public:
    CmdDrawArcBy3PtsGridNew() : CmdDrawGridNewBase(ID_CMD_DRAWING_ARC_GRIDNEW_BY3PTS) {}
    ~CmdDrawArcBy3PtsGridNew() {}

public:
    virtual OwnerPtr<IAction> ExecuteCommand(const CommandParameters& cmdParams) override;

    OwnerPtr<IGraphicsNodeGroup> OnChordUpdated(IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt);
    OwnerPtr<IGraphicsNodeGroup> OnArcUpdated(IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt, const Vector3d& onArcPt);
    ElementId OnArcFinished(IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt,
        const Vector3d& onArcPt, const ISnap* pStartSnap, const ISnap* pEndSnap);

    void OnEnterGettingStartPointState(IUiView* pCurrentView);
    void OnEnterGettingEndPointState(IUiView* pCurrentView);
    void OnEnterGettingOnArcPointState(IUiView* pCurrentView);

    const std::wstring DefinePromptMessage(DrawArcBy3PointsStatus status);

};

OwnerPtr<IAction> CmdDrawArcBy3PtsGridNew::ExecuteCommand(const CommandParameters& cmdParams)
{
    CmdDrawGridNewBase* pCmdBase = static_cast<CmdDrawGridNewBase*>(this);

    ActionDrawArcBy3PtsElementInput actionInput;
    actionInput.CommandId = GetCommandId();
    actionInput.DrawArcMode = DrawArcBy3PointsMode::Separated;
    actionInput.PreviewArcEnabled = false;

    actionInput.ActionInitCallback = ActionDrawArcBy3PtsElementInput::CreateOnActionInitCallback(&CmdDrawGridNewBase::OnActionInit, pCmdBase);
    actionInput.PromptMessageCallback = ActionDrawArcBy3PtsElementInput::CreateDefinePomptMessageCallback(&CmdDrawArcBy3PtsGridNew::DefinePromptMessage, this);
    actionInput.EnterGettingStartPointStateCallback = ActionDrawArcBy3PtsElementInput::CreateOnEnterGettingStartPointStateCallback(
        &CmdDrawArcBy3PtsGridNew::OnEnterGettingStartPointState, this);
    actionInput.EnterGettingEndPointStateCallback = ActionDrawArcBy3PtsElementInput::CreateOnEnterGettingEndPointStateCallback(
        &CmdDrawArcBy3PtsGridNew::OnEnterGettingEndPointState, this);
    actionInput.ChordUpdateCallback = ActionDrawArcBy3PtsElementInput::CreateOnChordUpdateCallback(&CmdDrawArcBy3PtsGridNew::OnChordUpdated, this);
    actionInput.ArcUpdateCallback = ActionDrawArcBy3PtsElementInput::CreateOnArcUpdateCallback(&CmdDrawArcBy3PtsGridNew::OnArcUpdated, this);
    actionInput.ArcFinishedCallback = ActionDrawArcBy3PtsElementInput::CreateOnArcFinishedCallback(&CmdDrawArcBy3PtsGridNew::OnArcFinished, this);
    actionInput.ActionDestroyCallback = ActionDrawArcBy3PtsElementInput::CreateOnActionDestroyCallback(&CmdDrawGridNewBase::OnActionDestroy, pCmdBase);

    std::vector<Int64> priorityTypes;
    priorityTypes.emplace_back(typeid(IGridNew).hash_code());
    actionInput.SnapCandidatesPreprocessor = NEW_AS_OWNER_PTR(GbmpSnapEndPointPriorityTypesPreprocessor, priorityTypes);

    OwnerPtr<IAction> opAction = ActionDrawArcBy3PtsElementCreator::Create(actionInput);

    // 开启动态面板
    AddStructureDynamicPannelUtil::SetupGridNewCreationContext(opAction.get(), ID_PAGE_GBMP_MODIFY);

    return TransferOwnership(opAction);
}

OwnerPtr<IGraphicsNodeGroup> CmdDrawArcBy3PtsGridNew::OnChordUpdated(IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt)
{
    if (Vector2dUtils::IsEqual(startPt.Vec2d(), endPt.Vec2d()))
    {
        return nullptr;
    }

    OwnerPtr<ILine3d> opLine = ILine3d::Create(startPt, endPt);
    return CreatePreviewGraphics(pCurrentView, opLine.get());
}

OwnerPtr<IGraphicsNodeGroup> CmdDrawArcBy3PtsGridNew::OnArcUpdated(
    IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt, const Vector3d& onArcPt)
{
    if (Vector2dUtils::IsEqual(startPt.Vec2d(), endPt.Vec2d())
        || Vector2dUtils::IsEqual(startPt.Vec2d(), onArcPt.Vec2d())
        || Vector2dUtils::IsEqual(endPt.Vec2d(), onArcPt.Vec2d()))
    {
        return nullptr;
    }

    OwnerPtr<IArc3d> opArc = IArc3d::Create(startPt, endPt, onArcPt);
    return CreatePreviewGraphics(pCurrentView, opArc.get());
}

ElementId CmdDrawArcBy3PtsGridNew::OnArcFinished(IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt,
    const Vector3d& onArcPt, const ISnap* pStartSnap, const ISnap* pEndSnap)
{
    OwnerPtr<IArc3d> opArc = IArc3d::Create(startPt, endPt, onArcPt);
    IGridNew* pGrid = this->CreateGridElement(pCurrentView, opArc.get());
    DBG_WARN_AND_RETURN_UNLESS(pGrid, ElementId::InvalidID, L"pGrid为空，轴网创建失败。",L"GDMPLab",L"2024-03-30");

    // 提交事务组并合并为一个事务
    UserTransactionGroupUtils::CommitLatestActiveWithTransactionsMergedIntoOne(UiDocumentViewUtils::GetCurrentDocument());
    // 启动新的事务组
    UserTransactionGroupUtils::Start(UiDocumentViewUtils::GetCurrentDocument(), GBMP_TR(L"创建单条轴网事务组"), m_utxGroupIdx);

    return pGrid->GetOwnerElement()->GetElementId();
}

void CmdDrawArcBy3PtsGridNew::OnEnterGettingStartPointState(IUiView* pCurrentView)
{
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);
}

void CmdDrawArcBy3PtsGridNew::OnEnterGettingEndPointState(IUiView* pCurrentView)
{
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);
}

void CmdDrawArcBy3PtsGridNew::OnEnterGettingOnArcPointState(IUiView* pCurrentView)
{
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);
}

const std::wstring CmdDrawArcBy3PtsGridNew::DefinePromptMessage(DrawArcBy3PointsStatus status)
{
    switch (status)
    {
    case DrawArcBy3PointsStatus::Getting_StartPoint:
        return GBMP_TR(L"绘制轴网 - 请输入圆弧起始点");
    case DrawArcBy3PointsStatus::Getting_EndPoint:
        return GBMP_TR(L"绘制轴网 - 请输入圆弧终止点");
    case DrawArcBy3PointsStatus::Getting_OnArcPoint:
        return GBMP_TR(L"绘制轴网 - 请输入圆弧弧上一点");
    default:
        return L"";
    }
}

REGISTER_GM_COMMAND(CmdDrawLineGridNew);
REGISTER_GM_COMMAND(CmdDrawArcBy3PtsGridNew);
